package com.qianniu.napi.common.util;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Strings;
import com.qianniu.napi.admin.entity.MerchantApp;
import com.qianniu.napi.admin.entity.User;
import com.qianniu.napi.admin.service.IRedisService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.session.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.util.*;

/**
 * Created by chenxuebin on 2017/8/10.
 */
public class ObjectUtil {

    private static final Logger logger = LoggerFactory.getLogger(ObjectUtil.class);

    public static Object mapToObject(Map<String, Object> map, Class<?> beanClass) {
        if (map == null)
            return null;

        try {
            Object obj = beanClass.newInstance();

            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                Method setter = property.getWriteMethod();
                if (setter != null) {
                    setter.invoke(obj, map.get(property.getName()));
                }
            }
            return obj;
        } catch (Exception e) {
            logger.error(">>> ObjectUtil mapToObject error", e);
        }

        return null;
    }

    public static Map<String, Object> objectToMap(Object obj) throws Exception {
        if (obj == null)
            return null;

        Map<String, Object> map = new HashMap<String, Object>();

        BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor property : propertyDescriptors) {
            String key = property.getName();
            if (key.compareToIgnoreCase("class") == 0) {
                continue;
            }
            Method getter = property.getReadMethod();
            Object value = getter != null ? getter.invoke(obj) : null;
            map.put(key, value);
        }

        return map;
    }

    public static String getObjectField(Object obj, String field) {
        if (obj == null)
            return null;

        Map<String, Object> map = new HashMap<String, Object>();

        try {

            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                if (!key.equals(field)) continue;

                if (key.compareToIgnoreCase("class") == 0) {
                    continue;
                }
                Method getter = property.getReadMethod();
                return getter != null ? getter.invoke(obj).toString() : null;
            }
        } catch (Exception e) {

        }

        return null;
    }

    public static int getByteSize(String content) {
        int size = 0;
        if (null != content) {
            try {
                // 汉字采用utf-8编码时占3个字节
                size = content.getBytes("utf-8").length;
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return size;
    }

    /*
     * 输出指定长度数字+字母字符串
     */
    public static List<String> randomStrings(int length, int num) {

        List<String> results = new ArrayList<String>();

        for (int j = 0; j < num; j++) {
            String val = "";

            Random random = new Random();
            for (int i = 0; i < length; i++) {
                String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num"; // 输出字母还是数字

                if ("char".equalsIgnoreCase(charOrNum)) // 字符串
                {
                    int choice = random.nextInt(2) % 2 == 0 ? 65 : 97; //取得大写字母还是小写字母
                    val += (char) (choice + random.nextInt(26));
                } else if ("num".equalsIgnoreCase(charOrNum)) // 数字
                {
                    val += String.valueOf(random.nextInt(10));
                }
            }
            val = val.toLowerCase();
            if (results.contains(val)) {
                continue;
            } else {
                results.add(val);
            }
        }
        return results;
    }

    /*
     * 输出指定长度数字子串
     */
    public static String randomNum(int length) {

        String val = "";
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            val += String.valueOf(random.nextInt(10));// 输出数字
        }
        val = val.toLowerCase();
        return val;
    }

    /*
     * 输出指定长度数字子串
     */
    public static List<String> randomNum(int length, int num) {

        List<String> results = new ArrayList<String>();

        for (int j = 0; j < num; j++) {
            String val = "";

            Random random = new Random();
            for (int i = 0; i < length; i++) {
                val += String.valueOf(random.nextInt(10));// 输出数字
            }
            val = val.toLowerCase();
            if (results.contains(val)) {
                continue;
            } else {
                results.add(val);
            }
        }
        return results;
    }

    public static Long getUid() {
        Session s = SecurityUtils.getSubject().getSession();
        if (s.getAttribute("uid") == null || s.getAttribute("uid").toString().equals("")) {
            User user = ObjectUtil.getSessionUser();
            if (user == null) {
                return null;
            }
            return user.getId();
        }
        return Long.valueOf(s.getAttribute("uid").toString());
    }

    public static String getCname() {
        Session s = SecurityUtils.getSubject().getSession();
        if (s.getAttribute("cname") == null || s.getAttribute("cname").toString().equals("")) {
            User user = ObjectUtil.getSessionUser();
            if (user == null) {
                return null;
            }
            return user.getName();
        }
        return s.getAttribute("cname").toString();
    }

    public static int getIsAdmin() {

        Long mid = ObjectUtil.getMid();
        int isAdmin = 0;
        if (mid != null && mid == 0) {
            isAdmin = 1;
        }
        return isAdmin;
    }

    public static Long getMid() {
        Session s = SecurityUtils.getSubject().getSession();
        if (s.getAttribute("mid") == null || s.getAttribute("mid").toString().equals("")) {
            User user = ObjectUtil.getSessionUser();
            if (user == null) {
                return null;
            }

            return user.getMid();
        }
        return Long.valueOf(s.getAttribute("mid").toString());
    }

    // key = mid+"__"+mpid+"__uid__"+ ObjectUtil.randomStrings(8,1).get(0)+"__"+ma.getAppid()+"__"+ma.getAppType()[+"__"+sid+"__"+subsid][+"##"+main mpid];
    public static String getKey(User user, Long mpid) {
        String key = null;
        if (user != null) {
            IRedisService redisService = (IRedisService) SpringUtil.getBean("redisServiceImpl");
            MerchantApp mapp = redisService.getMApp(user.getMpid());
            key = user.getMid() + "__" + user.getMpid() + "__" + user.getId() + "__" + ObjectUtil.randomStrings(8, 1).get(0) + "__" + mapp.getAppid() + "__" + mapp.getAppType();
            if (user.getSid() != null) key += "__" + user.getSid();
            if (user.getSubsid() != null) key += "__" + user.getSubsid();
            logger.info("======user!=null==getToken key=" + key);
        } else {
            key = getMid() + "__" + getMpid() + "__" + getUid() + "__" + ObjectUtil.randomStrings(8, 1).get(0) + "__" + getAppid() + "__" + getAppType();
        }
        if (mpid != null && user.getMpid() != mpid) key += "##" + mpid;
        logger.info("========getToken key=" + key);
        return key;
    }

    public static String getMcode() {
        Session s = SecurityUtils.getSubject().getSession();
        return s.getAttribute("mcode").toString();
    }

    public static String getAppid() {
        Session s = SecurityUtils.getSubject().getSession();
        Object appid = s.getAttribute("appid");
        return appid == null ? null : appid.toString();
    }

    public static Long getSid() {
        Session s = SecurityUtils.getSubject().getSession();
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        Object sid = s.getAttribute("sid");
        return sid == null ? user == null ? null : user.getSid() : Long.valueOf(sid.toString());
    }

    public static Long getSubsid() {
        Session s = SecurityUtils.getSubject().getSession();
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        Object subsid = s.getAttribute("subsid");
        return subsid == null ? user == null ? null : user.getSubsid() : Long.valueOf(subsid.toString());
    }

    public static Long getMpid() {
        Session s = SecurityUtils.getSubject().getSession();
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        return s.getAttribute("mpid") == null ? user == null ? null : user.getMpid() : Long.valueOf(s.getAttribute("mpid").toString());
    }

    public static Long getMainmpid() {
        Session s = SecurityUtils.getSubject().getSession();
        return s.getAttribute("mainmpid") == null ? null : Long.valueOf(s.getAttribute("mainmpid").toString());
    }

    public static int getUserType() {
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        logger.info("========getUserType");
        logger.info(JSON.toJSONString(user));
        int utype = user.getUserType() == null ? 0 : user.getUserType();
        return utype;
    }

    public static String getAppType() {
        Session s = SecurityUtils.getSubject().getSession();
        Object appType = s.getAttribute("appType");
        return appType == null ? "" : appType.toString();
    }

    public static User getSessionUser() {
        logger.info("======getSubject=", SecurityUtils.getSubject());
        logger.info("======getPrincipal=", SecurityUtils.getSubject().getPrincipal());
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        logger.info("==========getSessionUser=" + JSON.toJSONString(user));
        return user;
    }

    public static String getIP(HttpServletRequest req) {
//
//        String ipAddress = req.getRemoteAddr();
//        if (ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")) {
//            //根据网卡获取本机配置的IP地址
//            InetAddress inetAddress = null;
//            try {
//                inetAddress = InetAddress.getLocalHost();
//            } catch (UnknownHostException e) {
//                logger.error("getIP error", e);
//            }
//            ipAddress = inetAddress.getHostAddress();
//        }
//        //对于通过多个代理的情况，第一个IP为客户端真实的IP地址，多个IP按照','分割
//        if (null != ipAddress && ipAddress.length() > 15) {
//            if (ipAddress.indexOf(",") > 0) {
//                ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
//            }
//        }
//        return ipAddress;
        return getIP();
    }

    public static String getIP() {
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        // 设置IP地址
        String ip = IPUtils.getIpAddr(request);
        return ip;
    }

    public static String getLocation() {
        String ip = getIP();
        if (Strings.isNullOrEmpty(ip)) return "";
        if (ip.equals("127.0.0.1")) return "局域网";
        return AddressUtils.getCityInfo(getIP());
    }

    public static String getPwd(String ori, String salt, int terater) {

        logger.info("======getPwd ori=" + ori + " salt=" + salt + " terater=" + terater);
        String hashAlgorithmName = "MD5";
        int hashIterations = 3;
//        Object obj = new SimpleHash(hashAlgorithmName, ori, null, hashIterations);

        String result = new Md5Hash(ori, salt, 3).toString();
        logger.info("======pwd result=" + result);
        return result;
    }

    public static void main(String[] args) {

//        DiseaseDO bean = new DiseaseDO();
//        bean.setReason("hehe");
//        System.out.println("result="+getObjectField(bean,"reason"));
//        System.out.println(RegexUtil.REGEX_PRECRIPTION.matcher("治疗肚子疼有什么方子推荐").find());

    }
}
